use bytesio::bytes_errors::{BytesReadError, BytesWriteError};
use failure::{Backtrace, Fail};
use std::fmt;
use std::fmt::Error;
use std::time::SystemTimeError;

// 摘要错误结构体
#[derive(Debug)]
pub struct DigestError {
    pub value: DigestErrorValue,
}

#[derive(Debug, Fail)]
pub enum DigestErrorValue {
    // 字节读取错误
    #[fail(display = "bytes read error: {}", _0)]
    BytesReadError(BytesReadError),
    // 摘要长度不正确错误
    #[fail(display = "digest length not correct")]
    DigestLengthNotCorrectError,
    // 无法生成摘要错误
    #[fail(display = "cannot generate digest")]
    CannotGenerate,
    // 未知模式错误
    #[fail(display = "unknow schema")]
    UnknowSchema,
}

impl From<BytesReadError> for DigestError {
    fn from(err: BytesReadError) -> DigestError {
        DigestError {
            value: DigestErrorValue::BytesReadError(err),
        }
    }
}

impl fmt::Display for DigestError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.value, f)
    }
}

// 实现 'Fail' Trait 用于错误处理
impl Fail for DigestError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.value.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.value.backtrace()
    }
}

// 握手错误结构体
#[derive(Debug)]
pub struct HandshakeError {
    pub value: HandshakeErrorValue,
}

// 握手错误枚举类型
#[derive(Debug, Fail)]
pub enum HandshakeErrorValue {
    // 字节读取错误
    #[fail(display = "bytes read error: {}", _0)]
    BytesReadError(BytesReadError),
    // 字节写入错误
    #[fail(display = "bytes write error: {}", _0)]
    BytesWriteError(BytesWriteError),
    // 系统时间错误
    #[fail(display = "system time error: {}", _0)]
    SystemTimeError(SystemTimeError),
    // 摘要错误错误
    #[fail(display = "digest error: {}", _0)]
    DigestError(DigestError),
    // 摘要未找到错误
    #[fail(display = "digest not found error")]
    DigestNotFoundError,
    // S0 版本不正确错误
    #[fail(display = "s0 version not correct error")]
    S0VersionNotCorrectError,
    // IO错误
    #[fail(display = "io error")]
    IOError(Error),
}

impl From<Error> for HandshakeError {
    fn from(error: Error) -> Self {
        HandshakeError {
            value: HandshakeErrorValue::IOError(error),
        }
    }
}

impl From<HandshakeErrorValue> for HandshakeError {
    fn from(value: HandshakeErrorValue) -> Self {
        HandshakeError { value }
    }
}

impl From<BytesReadError> for HandshakeError {
    fn from(error: BytesReadError) -> Self {
        HandshakeError {
            value: HandshakeErrorValue::BytesReadError(error),
        }
    }
}

impl From<BytesWriteError> for HandshakeError {
    fn from(error: BytesWriteError) -> Self {
        HandshakeError {
            value: HandshakeErrorValue::BytesWriteError(error),
        }
    }
}

impl From<SystemTimeError> for HandshakeError {
    fn from(error: SystemTimeError) -> Self {
        HandshakeError {
            value: HandshakeErrorValue::SystemTimeError(error),
        }
    }
}

impl From<DigestError> for HandshakeError {
    fn from(error: DigestError) -> Self {
        HandshakeError {
            value: HandshakeErrorValue::DigestError(error),
        }
    }
}

// 实现 'fmt::Dispaly' Trait 用于格式化输出 'HandshakeError'
impl fmt::Display for HandshakeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.value, f)
    }
}

// 实现 'Fail' Trait 用于错误处理
impl Fail for HandshakeError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.value.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.value.backtrace()
    }
}
